﻿using MasterMasterMode.Common.Systems;
using MasterMasterMode.Content.NPCs;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;

namespace MasterMasterMode.Common.GlobalNPCs
{
    public class BunnyNPC : GlobalNPC
    {
        public override bool InstancePerEntity => true;
        public override void OnKill(NPC npc)
        {
            if (ModContent.GetInstance<MasterMasterModeSystem>().MasterMasterMode)
            {
                if (npc.type == NPCID.Bunny && npc.lastInteraction == Main.myPlayer)
                {
                    SpawnGiantBunnyOffScreen(Main.player[npc.lastInteraction]);
                }
            }
        }
        private static void SpawnGiantBunnyOffScreen(Player player)
        {
            Rectangle screenRect = new((int)Main.screenPosition.X, (int)Main.screenPosition.Y, Main.screenWidth, Main.screenHeight);
            Vector2 spawnPosition = FindOffScreenPosition(player, screenRect);
            int giantBunnyIndex = NPC.NewNPC(player.GetSource_FromThis(), (int)spawnPosition.X, (int)spawnPosition.Y, ModContent.NPCType<GiantBunny>());
            if (giantBunnyIndex >= 0)
            {
                NPC giantBunny = Main.npc[giantBunnyIndex];
                giantBunny.target = player.whoAmI;

                AddSpawnEffects(spawnPosition);
            }
        }

        private static Vector2 FindOffScreenPosition(Player player, Rectangle screenRect)
        {
            for (int attempt = 0; attempt < 10; attempt++)
            {
                int direction = Main.rand.Next(4);
                Vector2 potentialPos = Vector2.Zero;
                switch (direction)
                {
                    case 0:
                        potentialPos = new Vector2(player.Center.X + Main.rand.Next(-200, 201), screenRect.Top - 200 - Main.rand.Next(100));
                        break;
                    case 1:
                        potentialPos = new Vector2(player.Center.X + Main.rand.Next(-200, 201), screenRect.Bottom + 200 + Main.rand.Next(100));
                        break;
                    case 2:
                        potentialPos = new Vector2(screenRect.Left - 200 - Main.rand.Next(100), player.Center.Y + Main.rand.Next(-200, 201));
                        break;
                    case 3:
                        potentialPos = new Vector2(screenRect.Right + 200 + Main.rand.Next(100), player.Center.Y + Main.rand.Next(-200, 201));
                        break;
                }
                if (IsValidOffScreenPosition(potentialPos, screenRect))
                {
                    return potentialPos;
                }
            }
            return new Vector2(screenRect.Left - 300, player.Center.Y);
        }

        private static bool IsValidOffScreenPosition(Vector2 position, Rectangle screenRect)
        {
            Point tilePos = (position / 16f).ToPoint();
            if (!WorldGen.InWorld(tilePos.X, tilePos.Y))
            {
                return false;
            }
            Rectangle extendedScreen = new(screenRect.X - 100, screenRect.Y - 100, screenRect.Width + 200, screenRect.Height + 200);
            if (extendedScreen.Contains(position.ToPoint()))
            {
                return false;
            }
            return IsValidGroundPosition(position);
        }

        private static bool IsValidGroundPosition(Vector2 position)
        {
            Point tilePos = (position / 16f).ToPoint();
            if (Main.tile[tilePos.X, tilePos.Y].HasTile && Main.tileSolid[Main.tile[tilePos.X, tilePos.Y].TileType])
            {
                return false;
            }
            for (int y = 1; y <= 3; y++)
            {
                if (WorldGen.InWorld(tilePos.X, tilePos.Y + y) && Main.tile[tilePos.X, tilePos.Y + y].HasTile && Main.tileSolid[Main.tile[tilePos.X, tilePos.Y + y].TileType])
                {
                    return true;
                }
            }
            return false;
        }
        private static void AddSpawnEffects(Vector2 position)
        {
            if (Main.netMode != NetmodeID.Server)
            {
                for (int i = 0; i < 5; i++)
                {
                    Dust.NewDustPerfect(position, DustID.Smoke, new Vector2(Main.rand.NextFloat(-1f, 1f), Main.rand.NextFloat(-1f, 1f)), 100, Color.Gray, 1f);
                }
            }
        }
    }
}
